import { NavigationGuardNext, RouteLocationRaw, RouteLocationNormalized, Router } from "vue-router";
import checkUpdate from "@/utils/checkUpdate";
import { getToken, nextTick } from "@/utils/shared";

// 路由守卫，阻止页面跳转
let preventLeaveValue = false;

// 导航后拦截的地址
let interceptRoute: null | RouteLocationRaw = null;

// 加载提示的实例对象
const loadingInstance: any = null;

/**
 * 阻止页面跳转
 * @returns {boolean}
 */
export const preventLeave = (): void => {
  preventLeaveValue = true;
};
/**
 * 允许页面跳转
 * @returns {boolean}
 */
export const allowLeave = (): void => {
  preventLeaveValue = false;
};

/**
 * 历史地址记录拦截
 * @param info{ go?: number; route: RawLocation; }
 */
export const replaceHistory = (info: { go?: number; route: RouteLocationRaw }): void => {
  interceptRoute = info.route;
  window.history.go(info.go);
};

/**
 * 添加路由守卫
 * @param vueRouter
 */
export default (vueRouter: Router): void => {
  // 异步组件加载提示
  vueRouter.beforeEach((to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) => {
    if (preventLeaveValue) {
      next(false);
      return;
    }
    if (!getToken() && to.matched.some(({ meta }) => !meta?.noLogin)) {
      // 未登录，但是页面需登录才能访问
      interceptRoute = { name: "login" };
    }
    if (interceptRoute !== null) {
      // 路由跳转劫持
      const tempRoute = interceptRoute;
      interceptRoute = null;
      next(tempRoute);
    } else {
      // 如果劫持的是同一个url不会触发afterEach
      next();
      // TODO：页面加载提示
    }
  });

  // 路由全局后置回调
  vueRouter.afterEach((to) => {
    nextTick().then(() => loadingInstance && loadingInstance.close());
    const last = to.matched[to.matched.length - 1];
    try {
      if (last?.meta && typeof last.meta.title === "string") {
        document.title = last.meta.title;
        // 这里写上其他改变标题的操作
      }
    } catch (e) {
      console.log(e);
    }
  });

  // 加载路由失败时检查服务端版本是否更新
  vueRouter.onError((err) => {
    checkUpdate().then((res) => {
      if (res) {
        alert("发现新版本，即将更新");
        window.location.reload();
      } else {
        console.log(err);
      }
    });
  });
};
